package com.yanqu.road.server.gameplayer.module.activity.gourdchild;

import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.args.ValueParamArgs;
import com.yanqu.road.entity.activity.gourdchild.*;
import com.yanqu.road.entity.activity.gourdchild.config.GourdLevelInfo;
import com.yanqu.road.entity.activity.gourdchild.config.GourdLevelLotusInfo;
import com.yanqu.road.entity.activity.gourdchild.config.GourdMountainControl;
import com.yanqu.road.entity.activity.gourdchild.config.GourdMountainItem;
import com.yanqu.road.entity.activity.gourdchild.enums.eGridObjectType;
import com.yanqu.road.entity.activity.gourdchild.enums.eMoveDirectionType;
import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.enums.eLogMoneyType;
import com.yanqu.road.entity.enums.ePlayerAttrType;
import com.yanqu.road.entity.enums.eSystemId;
import com.yanqu.road.entity.log.*;
import com.yanqu.road.logic.bussiness.activity.GourdChildBussiness;
import com.yanqu.road.logic.helper.CalcPowerResult;
import com.yanqu.road.logic.helper.PowerHelper;
import com.yanqu.road.pb.activity.GourdChildProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.player.AttributeModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.gameplayer.module.player.PreReduceModule;
import com.yanqu.road.server.manger.activity.ActivityMgr;
import com.yanqu.road.server.manger.activity.gourdchild.GourdChildMgr;
import com.yanqu.road.server.manger.activity.gourdchild.MoveMergerResult;
import com.yanqu.road.server.manger.config.GoodsMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.log.LogMgr;
import com.yanqu.road.server.pb.GourdChildPb;
import com.yanqu.road.server.pb.PlayerPb;
import com.yanqu.road.server.protocol.CrossProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigInteger;
import java.util.*;

public class GourdChildModule extends GeneralModule {

    private GourdChildUserData userData;

    public GourdChildModule(GamePlayer player) {
        super(player);
    }

    @Override
    public boolean loadData() {
        GourdChildConfig config = GourdChildMgr.getConfig();
        if (config != null && ActivityMgr.activityInShowTime(config.getActivityInfo())) {
            userData = GourdChildBussiness.getGourdChildUserData(config.getActivityInfo().getActivityId(), getUserId());
        }
        return true;
    }

    @Override
    public boolean afterLoadData() {
        return false;
    }

    @Override
    public boolean saveData() {
        if (userData != null) {
            if (userData.isInsertOption()) {
                GourdChildBussiness.addGourdChildUserData(userData);
            } else if (userData.isUpdateOption()) {
                GourdChildBussiness.updateGourdChildUserData(userData);
            }
        }
        return true;
    }

    @Override
    public void afterLogin() {
        syncConfig();
        initUserData();
        syncUserData();
        syncGameData();
    }

    /**
     * 同步配置
     */
    public void syncConfig() {
        GourdChildConfig config = GourdChildMgr.getConfig();
        if (config == null || !ActivityMgr.activityInShowTime(config.getActivityInfo())) {
            return;
        }

        GourdChildProto.GourdChildSyncConfigRespMsg.Builder builder = GourdChildPb.parseSyncConfigRespMsg(config, player.getLanguage());
        player.sendPacket(Protocol.U_GOURD_CHILD_SYNC_CONFIG, builder);
    }

    /**
     * 同步玩家数据
     */
    public void syncUserData() {
        GourdChildConfig config = GourdChildMgr.getConfig();
        if (config == null || !ActivityMgr.activityInShowTime(config.getActivityInfo())) {
            return;
        }
        GourdChildUserData data = getUserData();
        if (data == null) {
            return;
        }

        //去掉最高历史的限制，直接给最高关卡
        if(data.getHistoryPassId() < 100000){
            data.setHistoryPassId(100000);
        }

        GourdChildProto.GourdChildSyncUserDataRespMsg.Builder builder = GourdChildProto.GourdChildSyncUserDataRespMsg.newBuilder();
        builder.setEnergy(data.getEnergy());
        builder.setLastRecTime(data.getLastRecTime());
        player.sendPacket(Protocol.U_GOURD_CHILD_SYNC_USER_DATA, builder);
    }

    public void syncGameData() {
        GourdChildConfig config = GourdChildMgr.getConfig();
        if (config == null || !ActivityMgr.activityInShowTime(config.getActivityInfo())) {
            return;
        }
        GourdChildUserData data = getUserData2();
        if (data == null) {
            return;
        }

        GourdChildProto.GourdChildGetGameDataSyncMsg.Builder builder = GourdChildProto.GourdChildGetGameDataSyncMsg.newBuilder();
        GourdChildProto.GourdChildGameDataMsg.Builder gameDataBuilder = GourdChildPb.parseGameDataMsg(data, config);
        GourdChildMgr.appendMovableData(gameDataBuilder, data.getGridList(), config);
        builder.setGameData(gameDataBuilder);
        player.sendPacket(Protocol.U_GOURD_CHILD_SYNC_GAME_DATA, builder);
    }

    /**
     * 初始化玩家数据
     */
    public synchronized void initUserData() {
        // 系统未解锁
        if (!SystemOpenMgr.systemOpen(player, eSystemId.GourdChildActivity.getValue())) {
            return;
        }

        // 没有活动
        GourdChildConfig config = GourdChildMgr.getConfig();
        if (config == null || !ActivityMgr.activityInShowTime(config.getActivityInfo())) {
            return;
        }

        ActivityInfo activityInfo = config.getActivityInfo();

        // 已经有数据了
        if (userData != null && userData.getActivityId() == activityInfo.getActivityId()) {
            return;
        }

        GourdChildUserData tmpUserData = new GourdChildUserData();
        tmpUserData.setActivityId(activityInfo.getActivityId());
        tmpUserData.setUserId(getUserId());
        tmpUserData.setScore(0);
        tmpUserData.setEnergy(config.getInitEnergy());
        tmpUserData.setLastRecTime(System.currentTimeMillis());
        tmpUserData.setLotusLv(1);

//        int historyPassId = (int)player.getModule(AttributeModule.class).getAttribute(ePlayerAttrType.GourdChildActivityMaxPassId);
//        tmpUserData.setHistoryPassId(historyPassId);
        tmpUserData.setHistoryPassId(100000);


        // 格子数据初始化
        List<Grid> gridList = new ArrayList<>();

        tmpUserData.setGridList(gridList);
        tmpUserData.setInsertOption();
        userData = tmpUserData;
    }

    /**
     * 获取玩家数据（不计算体力）
     */
    public GourdChildUserData getUserData2(){
        return userData;
    }

    /**
     * 获取玩家数据（计算体力）
     */
    public GourdChildUserData getUserData() {

        // 检查体力恢复
        GourdChildConfig config = GourdChildMgr.getConfig();
        if (userData != null && config != null) {

            int logBeforeEnergy = userData.getEnergy();

            CalcPowerResult result = PowerHelper.calcPower(
                    userData.getLastRecTime() / 1000,
                    config.getEnergyRecTime(),
                    config.getEnergyRecCount(),
                    config.getMaxEnergy(),
                    userData.getEnergy());
            userData.setEnergy(result.getCurPower());
            log.debug("user {} set energy {}", player.getUserId(), result.getCurPower());
            userData.setLastRecTime(result.getLastRecoverTime() * 1000);

            // 日志
            if (userData.getEnergy() != logBeforeEnergy) {
                AutoLogMgr.add(new LogGourdChildEnergy(userData.getUserId(), userData.getActivityId(), 4, userData.getEnergy() - logBeforeEnergy, userData.getEnergy()));
            }
        }

        return userData;
    }

    /**
     * 使用体力药
     */
    public int useEnergyItem(int count) {

        if (count <= 0 || count > 99999) {
            return GameErrorCode.E_GOURD_CHILD_ACTIVITY_USE_COUNT_ERROR;
        }

        GourdChildConfig config = GourdChildMgr.getConfig();
        Property cost = new Property();
        cost.addProperty(config.getEnergyRecItemId(), BigInteger.valueOf(count));

        // 计算恢复数量
        GoodsInfo goodsInfo = GoodsMgr.getGoodsById(config.getEnergyRecItemId());
        BigInteger energyCount = goodsInfo.getParamList().get(0);
        int totalCount = energyCount.intValue() * count;

        // 扣道具
        if (!player.getModule(CurrencyModule.class).removeCurrency(cost, eLogMoneyType.GourdChildActivity, eLogMoneyType.GourdChildUseEnergyItemCost)) {
            return GameErrorCode.E_GOURD_CHILD_ACTIVITY_ITEM_NO_ENOUGH;
        }

        // 加体力
        userData.setEnergy(userData.getEnergy() + totalCount);

        if (userData.getEnergy() > config.getMaxEnergy()) {
            userData.setLastRecTime(System.currentTimeMillis());
        }

        GourdChildProto.GourdChildUseEnergyItemRespMsg.Builder builder = GourdChildProto.GourdChildUseEnergyItemRespMsg.newBuilder();
        builder.setRet(0);
        builder.setEnergy(userData.getEnergy());
        builder.setLastRecTime(userData.getLastRecTime());
        player.sendPacket(Protocol.U_GOURD_CHILD_USE_ENERGY_ITEM, builder);

        // 日志
        AutoLogMgr.add(new LogGourdChildEnergy(userData.getUserId(), userData.getActivityId(), 3, count, userData.getEnergy()));
        return 0;
    }

    /**
     * 扣体力
     */
    public boolean reduceEnergy(int count, int type) {
        if (userData.getEnergy() < count)
            return false;

        GourdChildConfig config = GourdChildMgr.getConfig();
        int maxEnergy = config.getMaxEnergy();
        boolean aboveMaxBefore = userData.getEnergy() >= maxEnergy;

        userData.setEnergy(userData.getEnergy() - count);

        if (aboveMaxBefore) {
            userData.setLastRecTime(System.currentTimeMillis());
        }

        // 日志
        AutoLogMgr.add(new LogGourdChildEnergy(userData.getUserId(), userData.getActivityId(), type, count, userData.getEnergy()));
        return true;
    }

    /**
     * 获取游戏数据
     */
    public int getGameData(int passId, boolean train) {
        GourdChildConfig config = GourdChildMgr.getConfig();
        if(train){
            //练习模式，每次进入都是新数据
            //根据当前关卡进度（最高）的难度来选择
            if(userData.getPassDetail().getPassId() != 0){
                return GameErrorCode.E_GOURD_CHILD_ACTIVITY_TRAIN_NO_ENTRY;
            }
            passId = userData.getPassId();
            if(userData.getPassId() == 0){
                passId = config.getStartLevel().getId();
            }else {
                GourdLevelInfo curLevel = config.getLevelInfoMap().get(passId);
                if(curLevel.getNext() != null){
                    passId = curLevel.getNext().getId();
                }
            }
            GourdLevelInfo levelInfo = config.getLevelInfoMap().get(passId);
            userData.setTempGridList(GourdChildMgr.initGrid(GourdChildMgr.GRID_SIDE_LENGTH, config.getDefaultUnitNum(), levelInfo.getElement()));
            GourdChildPassDetail passDetail = new GourdChildPassDetail();
            passDetail.setBlood(Integer.MAX_VALUE);
            passDetail.setAllRound(Integer.MAX_VALUE);
            passDetail.setPassId(passId);
            userData.setTempPassDetail(passDetail);
            Grid nextGrid = generateNextGrid(levelInfo, userData.getTempGridList());
            userData.setTempNextGrid(nextGrid);

            GourdChildProto.GourdChildGetGameDataRespMsg.Builder respMsg = GourdChildProto.GourdChildGetGameDataRespMsg.newBuilder();
            respMsg.setRet(0);
            GourdChildProto.GourdChildGameDataMsg.Builder gameData = GourdChildPb.parseTrainGameDataMsg(userData, config);
            GourdChildMgr.appendMovableData(gameData, userData.getTempGridList(), config);
            respMsg.setGameData(gameData);
            player.sendPacket(Protocol.U_GOURD_CHILD_GET_GAME_DATA, respMsg);

        }else {
            int currPassId;
            if(passId > 0){
                //挑战关卡，是否可切换（当前关卡未结束，不可挑战）
                if(userData.getPassDetail().getPassId() > 0 && passId != userData.getPassDetail().getPassId()){
                    return GameErrorCode.E_GOURD_CHILD_ACTIVITY_UN_CHALLENGE;
                }
                //关卡不存在
                if(!config.getLevelInfoMap().containsKey(passId)){
                    return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
                }
                //初始只能挑战第一关
                if(userData.getPassId() == 0 && passId != config.getStartLevel().getId()){
                    return GameErrorCode.E_GOURD_CHILD_ACTIVITY_UN_CHALLENGE_AFTER_PASS;
                }else if(userData.getPassId() != 0){
                    //不可挑战，未通关的关卡（或是没有星级的关卡）
                    GourdLevelInfo levelInfo = config.getLevelInfoMap().get(userData.getPassId());
                    if (passId > userData.getPassId() && passId != levelInfo.getNext().getId()) {
                        return GameErrorCode.E_GOURD_CHILD_ACTIVITY_UN_CHALLENGE_AFTER_PASS;
                    }
                }
                currPassId = passId;
            }else {
                currPassId = userData.getPassId() == 0 ? config.getStartLevel().getId() : userData.getPassId();
            }
            GourdLevelInfo levelInfo = config.getLevelInfoMap().get(currPassId);
            //初始化
            if(userData.getPassDetail().getPassId() == 0){
                getUserData();
                int costEnergy = levelInfo.getEnergy();
                // 体力
                if (userData.getEnergy() < costEnergy) {
                    return GameErrorCode.E_GOURD_CHILD_ACTIVITY_ENERGY_NO_ENOUGH;
                }
                userData.setGridList(GourdChildMgr.initGrid(GourdChildMgr.GRID_SIDE_LENGTH, config.getDefaultUnitNum(), levelInfo.getElement()));
                //log.debug("userId {} init grid passId {} element {}", player.getUserId(), currPassId, levelInfo.getElement());
                userData.getPassDetail().setRound(0);
                userData.getPassDetail().setBlood(levelInfo.getHp());
                userData.getPassDetail().setPassId(currPassId);
                // 扣体力
                reduceEnergy(costEnergy, 1);
            }
            //下一个格子数据
            if(userData.getNextGrid().getData().size() == 0){
                userData.setNextGrid(generateNextGrid(levelInfo, userData.getGridList()));
            }

            GourdChildProto.GourdChildGetGameDataRespMsg.Builder respMsg = GourdChildProto.GourdChildGetGameDataRespMsg.newBuilder();
            respMsg.setRet(0);
            GourdChildProto.GourdChildGameDataMsg.Builder gameData = GourdChildPb.parseGameDataMsg(userData, config);
            GourdChildMgr.appendMovableData(gameData, userData.getGridList(), config);
            respMsg.setGameData(gameData);
            player.sendPacket(Protocol.U_GOURD_CHILD_GET_GAME_DATA, respMsg);

        }
        return 0;
    }

    /**
     * 移动
     */
    public MoveMergerResult moveGrid(int direction) {
        //判定方向参数合法
        MoveMergerResult moveMergerResult = new MoveMergerResult();
        eMoveDirectionType directionType = null;
        for (eMoveDirectionType value : eMoveDirectionType.values()) {
            if(value.getType() == direction){
                directionType = value;
            }
        }
        if(directionType == null){
            moveMergerResult.setRet(GameErrorCode.E_REQUEST_ARGUMENT_ERROR);
            return moveMergerResult;
        }
        //判定关卡是否有进度
        if(userData.getPassDetail().getPassId() == 0){
            moveMergerResult.setRet(GameErrorCode.E_GOURD_CHILD_ACTIVITY_GRID_NO_INIT);
            return moveMergerResult;
        }

        GourdChildConfig config = GourdChildMgr.getConfig();

        int passId = userData.getPassDetail().getPassId();
        GourdLevelInfo levelInfo = config.getLevelInfoMap().get(passId);

        // 移动逻辑
        moveMergerResult = GourdChildMgr.move(userData.getGridList(), directionType);
        if(moveMergerResult.getRet() != 0){
            return moveMergerResult;
        }

        // 计算攻击
        int damage = GourdChildMgr.getDamage(moveMergerResult, config, userData.getLotusLv());
        GourdLevelLotusInfo lotusInfo = config.getLotusInfoMap().get(userData.getLotusLv());
        // 攻击逻辑
        int blood = userData.getPassDetail().getBlood();
        // 是否结束（血量或者回合数）
        int round = userData.getPassDetail().getRound();
        int maxRound = levelInfo.getMaxRound();
        boolean end = damage >= blood;
        boolean win = end;
        if(!end){
            end = round + 1 >= maxRound;
        }
        // 本局单步伤害最高
        if(damage > userData.getPassDetail().getHighDamage()) {
            userData.getPassDetail().setHighDamage(damage);
        }
        // 历史单步伤害最高
        if(damage > userData.getNormalDamage()){
            userData.setNormalDamage(damage);
        }
        if(userData.getPassDetail().getHighDamage() == userData.getNormalDamage()){
            moveMergerResult.setNewHigh(true);
        }
        //剩余血量
        int remainBlood = blood - damage;
        //剩余回合
        int remainRound = levelInfo.getMaxRound() - round - 1;
        //星级
        int star = 0;
        if(end){
            //结束
            if(win) {
                //更新星级
                star = updateStar(levelInfo, round, passId);
                //更新关卡
                if(passId > userData.getPassId()){
                    userData.setPassId(passId);
                }
                moveMergerResult.setStar(star);

                //更新历史最高
                int historyPassId = (int)player.getModule(AttributeModule.class).getAttribute(ePlayerAttrType.GourdChildActivityMaxPassId);
                if(passId > historyPassId){
                    player.getModule(AttributeModule.class).setAttribute(ePlayerAttrType.GourdChildActivityMaxPassId, passId);
                }
            }
            moveMergerResult.setHighDamage(userData.getPassDetail().getHighDamage());
            moveMergerResult.setRound(userData.getPassDetail().getRound() + 1);
            //清理盘面数据及关卡进度
            clearUserGameData();
        }else {
            userData.getPassDetail().setBlood(blood - damage);
            userData.getPassDetail().setRound(1 + round);
            if(moveMergerResult.getNewIndex() > -1){
                //将下一个格子填入，并清空提示
                moveMergerResult.getResultList().set(moveMergerResult.getNewIndex(), userData.getNextGrid());
                userData.setNextGrid(new Grid());
            }
            userData.setGridList(moveMergerResult.getResultList());
            //重新生成下一个格子提示
            if(userData.getNextGrid().empty()) {
                Grid nextGrid = generateNextGrid(levelInfo, userData.getGridList());
                userData.setNextGrid(nextGrid);
            }
        }

        moveMergerResult.setEnd(end);
        moveMergerResult.setWin(win);
        String reward = "";
        if(end){
            if(win){
                reward = levelInfo.getReward();
            }else {
                reward = levelInfo.getDefeatReward();
            }
            Property rewardProperty = PropertyHelper.parseStringToProperty(reward);
            if(win){
                rewardProperty.addProperty(getRandomReward(levelInfo.getRandomReward(), 1));
                reward = PropertyHelper.parsePropertyToString(rewardProperty);
            }
            //拿出奖励的积分
            addScoreAndRank(config, rewardProperty);
            player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.GourdChildActivity, eLogMoneyType.GourdChildGridEndGet);
            moveMergerResult.setReward(reward);

        }

        if(damage > 0 && damage >= userData.getNormalDamage()){
            //最高伤害冲榜
            player.notifyListener(eGamePlayerEventType.GourdChildDamageRank.getValue(), userData.getNormalDamage());
            player.notifyListener(eGamePlayerEventType.GourdChildDamageCrossRank.getValue(), userData.getNormalDamage());
        }
        userData.setUpdateOption();

        //日志
        List<String> mergeComb = new ArrayList<>();
        for (Grid grid : moveMergerResult.getAttackList()) {
            List<String> gridDetail = new ArrayList<>();
            for (GridData gridData : grid.getData()) {
                gridDetail.add(gridData.getOt() + ":" + gridData.getLv());
            }
            mergeComb.add(StringUtils.listToString(gridDetail, ";"));
        }
        //移动日志
        LogGourdChildMove moveLog = new LogGourdChildMove(player.getUserId(), config.getActivityId(), passId, 1, lotusInfo.getLevel(),
                damage, lotusInfo.getDamage(), StringUtils.listToString(mergeComb, "|"), remainBlood, remainRound);
        AutoLogMgr.add(moveLog);
        //结束日志
        if(end){
            int failType = win ? 0 : 2;
            LogGourdChildPass passLog = new LogGourdChildPass(player.getUserId(), config.getActivityId(), passId, win, star, failType, reward);
            AutoLogMgr.add(passLog);
        }
        return moveMergerResult;
    }

    /**
     * 关卡的随机奖励
     */
    private Property getRandomReward(String randomReward, int times) {
        Property property = new Property();
        if(StringUtils.isNullOrEmpty(randomReward)){
            return property;
        }
        List<Integer> weightList = new ArrayList<>();
        List<String> rewardList = new ArrayList<>();
        List<String> paramsList = StringUtils.stringToStringList(randomReward, "\\|");
        for (String param : paramsList) {
            List<String> data = StringUtils.stringToStringList(param, ";");
            if(data.size() != 2){
                return property;
            }
            weightList.add(Integer.valueOf(data.get(1)));
            rewardList.add(data.get(0));
        }
        if(weightList.size() == 0){
            return property;
        }
        Random random = new Random();
        for(int i = 0; i < times; i++){
            int idx = RandomHelper.getRandomIndexByWeight(weightList, random);
            property.addProperty(PropertyHelper.parseStringToProperty(rewardList.get(idx)));
        }
        return property;
    }

    /**
     * 获取总星级
     */
    private int getTotalStar() {
        int star = 0;
        for (Map.Entry<Integer, Integer> entry : userData.getPassStar().entrySet()) {
            star += entry.getValue();
        }
        return star;
    }

    /**
     * 练习场 移动
     */
    public int moveGridTrain(int direction) {
        eMoveDirectionType directionType = null;
        for (eMoveDirectionType value : eMoveDirectionType.values()) {
            if(value.getType() == direction){
                directionType = value;
            }
        }
        if(directionType == null){
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }

        if(userData.getTempPassDetail().getPassId() == 0){
            return GameErrorCode.E_GOURD_CHILD_ACTIVITY_GRID_NO_INIT;
        }

        GourdChildConfig config = GourdChildMgr.getConfig();
        int passId = userData.getTempPassDetail().getPassId();
        GourdLevelInfo levelInfo = config.getLevelInfoMap().get(passId);

        // 移动逻辑
        MoveMergerResult moveMergerResult = GourdChildMgr.move(userData.getTempGridList(), directionType);
        if(moveMergerResult.getRet() != 0){
            return moveMergerResult.getRet();
        }

        int damage = GourdChildMgr.getDamage(moveMergerResult, config, userData.getLotusLv());
        GourdLevelLotusInfo lotusInfo = config.getLotusInfoMap().get(userData.getLotusLv());
        // 本局单步伤害最高
        if(damage > userData.getTempPassDetail().getHighDamage()) {
            userData.getTempPassDetail().setHighDamage(damage);
        }
        // 历史单步伤害最高
        if(damage > userData.getTrainDamage()){
            userData.setTrainDamage(damage);
        }
        // 攻击逻辑
        int blood = userData.getTempPassDetail().getBlood();
        // 是否结束（血量或者回合数）
        int round = userData.getTempPassDetail().getRound();
        int maxRound = userData.getTempPassDetail().getAllRound();
        boolean end = damage >= blood;
        boolean win = end;
        //剩余血量
        int remainBlood = blood - damage;
        //剩余回合
        int remainRound = maxRound - round - 1;
        if(!end){
            end = round + 1 >= maxRound;
        }
        if(end) {
            if(damage > userData.getTrainDamage()){
                userData.setTrainDamage(damage);
                moveMergerResult.setNewHigh(true);
            }
            moveMergerResult.setRound(userData.getTempPassDetail().getRound());
            for (Grid grid : userData.getTempGridList()) {
                grid.getData().clear();
            }
            userData.setTempPassDetail(new GourdChildPassDetail());
        }else {
            userData.getTempPassDetail().setBlood(blood - damage);
            userData.getTempPassDetail().setRound(1 + round);
            if(moveMergerResult.getNewIndex() > -1){
                moveMergerResult.getResultList().set(moveMergerResult.getNewIndex(), userData.getTempNextGrid());
                userData.setTempNextGrid(new Grid());
            }
            userData.setTempGridList(moveMergerResult.getResultList());
            if(userData.getTempNextGrid().empty()) {
                Grid nextGrid = generateNextGrid(levelInfo, userData.getTempGridList());
                userData.setTempNextGrid(nextGrid);
            }
        }

        //日志
        List<String> mergeComb = new ArrayList<>();
        for (Grid grid : moveMergerResult.getAttackList()) {
            List<String> gridDetail = new ArrayList<>();
            for (GridData gridData : grid.getData()) {
                gridDetail.add(gridData.getOt() + ":" + gridData.getLv());
            }
            mergeComb.add(StringUtils.listToString(gridDetail, ";"));
        }
        //移动日志
        LogGourdChildMove moveLog = new LogGourdChildMove(player.getUserId(), config.getActivityId(), passId, 2, lotusInfo.getLevel(),
                damage, lotusInfo.getDamage(), StringUtils.listToString(mergeComb, "|"), remainBlood, remainRound);
        AutoLogMgr.add(moveLog);

        GourdChildProto.GourdChildMoveGridTrainRespMsg.Builder respMsg = GourdChildProto.GourdChildMoveGridTrainRespMsg.newBuilder();
        respMsg.setRet(0);
        GourdChildProto.GourdChildGameDataMsg.Builder gameData = GourdChildPb.parseTrainGameDataMsg(userData, GourdChildMgr.getConfig());
        GourdChildMgr.appendMovableData(gameData, userData.getTempGridList(), config);
        respMsg.setGameData(gameData);
        respMsg.setEnd(end);
        respMsg.setWin(win);
        respMsg.setRound(userData.getTempPassDetail().getRound());
        respMsg.addAllAttack(GourdChildPb.getGourdChildGridTemps(moveMergerResult.getAttackList()));
        respMsg.setHighDamage(moveMergerResult.getHighDamage());
        respMsg.addAllDamage(moveMergerResult.getAttackDamage());
        respMsg.setNewHigh(moveMergerResult.isNewHigh());
        player.sendPacket(Protocol.U_GOURD_CHILD_MOVE_GRID_TRAIN, respMsg);
        return 0;
    }

    /**
     * 生成下一个格子(按权重)
     */
    public Grid generateNextGrid(GourdLevelInfo levelInfo, List<Grid> gridList) {
        Grid nextGrid = new Grid();
        int allGridDataNum = 0;
        List<Integer> typeNum = new ArrayList<>();
        typeNum.add(0);//元素
        typeNum.add(0);//葫芦
        typeNum.add(0);//葫芦娃
        for (Grid grid : gridList) {
            for (GridData gridData : grid.getData()) {
                if(gridData.getOt() == eGridObjectType.GOURD.getType()){
                    typeNum.set(1, 1 + typeNum.get(1));
                }else if(gridData.getOt() == eGridObjectType.GOURD_CHILD.getType()){
                    typeNum.set(2, 1 + typeNum.get(2));
                }else {
                    typeNum.set(0, 1 + typeNum.get(0));
                }
                allGridDataNum++;
            }
        }
        List<Integer> weight = new ArrayList<>();
        weight.add(allGridDataNum - typeNum.get(0));//元素
        weight.add(allGridDataNum - typeNum.get(1));//葫芦
        weight.add(allGridDataNum - typeNum.get(2));//葫芦娃
        Random random = new Random();
        int idx = RandomHelper.getRandomIndexByWeight(weight, random);
        GridData gridData;
        if(idx == 0){
            gridData = GourdChildMgr.randomGridData(levelInfo.getElement());
        }else if(idx == 1){
            gridData = GourdChildMgr.newGridData(eGridObjectType.GOURD.getType(), 1);
        }else {
            gridData = GourdChildMgr.newGridData(eGridObjectType.GOURD_CHILD.getType(), 1);
        }
        nextGrid.getData().add(gridData);
        return nextGrid;
    }

    /**
     * 放弃当前关卡进度
     */
    public int endCurrentPass() {
        GourdChildProto.GourdChildEndCurrPassRespMsg.Builder respMsg = GourdChildProto.GourdChildEndCurrPassRespMsg.newBuilder();
        if(userData.getPassDetail().getPassId() > 0) {
            int passId = userData.getPassDetail().getPassId();
            GourdChildConfig config = GourdChildMgr.getConfig();
            GourdLevelInfo levelInfo = config.getLevelInfoMap().get(userData.getPassDetail().getPassId());
            String reward = levelInfo.getDefeatReward();
            respMsg.setHighDamage(userData.getPassDetail().getHighDamage());
            respMsg.setNewHigh(userData.getNormalDamage() == userData.getPassDetail().getHighDamage());
            //清理数据
            clearUserGameData();
            player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.GourdChildActivity,  eLogMoneyType.GourdChildGridEndGet);

            Property property = PropertyHelper.parseStringToProperty(reward);
            //积分及冲榜
            addScoreAndRank(config, property);

            respMsg.setReward(reward);
            syncGameData();
            //关卡日志
            LogGourdChildPass passLog = new LogGourdChildPass(player.getUserId(), config.getActivityId(), passId, false, 0, 1, reward);
            AutoLogMgr.add(passLog);
        }
        respMsg.setRet(0);
        player.sendPacket(Protocol.U_GOURD_CHILD_END_CURR_PASS, respMsg);
        return 0;
    }

    /**
     * 清理游戏关卡相关数据
     */
    public void clearUserGameData() {
        for (Grid grid : userData.getGridList()) {
            grid.getData().clear();
        }
        userData.setPassDetail(new GourdChildPassDetail());
        userData.setNextGrid(new Grid());
    }

    /**
     * 更新星级
     */
    public int updateStar(GourdLevelInfo levelInfo, int round, int passId) {
        int star = GourdChildMgr.getPassStar(round + 1, levelInfo.getStarLimit());
        if (userData.getPassStar().containsKey(passId)) {
            if (userData.getPassStar().get(passId) < star) {
                userData.getPassStar().put(passId, star);
                //星级成就
                player.notifyListener(eGamePlayerEventType.GourdChildPassTotalStar.getValue(), getTotalStar());
            }
        } else {
            userData.getPassStar().put(passId, star);
            //星级成就
            player.notifyListener(eGamePlayerEventType.GourdChildPassTotalStar.getValue(), getTotalStar());
        }
        return star;
    }

    /**
     * 升级彩莲
     */
    public int upgradeLotus() {
        GourdChildConfig config = GourdChildMgr.getConfig();
        if(userData.getLotusLv() == config.getLotusInfoMap().size()){
            return GameErrorCode.E_GOURD_CHILD_ACTIVITY_LOTUS_LEVEL_IS_MAX;
        }
        GourdLevelLotusInfo levelLotusInfo = config.getLotusInfoMap().get(userData.getLotusLv());
        Property consumer = PropertyHelper.parseStringToProperty(levelLotusInfo.getConsume());
        // 扣道具
        if (!player.getModule(CurrencyModule.class).removeCurrency(consumer, eLogMoneyType.GourdChildActivity, eLogMoneyType.GourdChildUseLotusUpgradeItemCost)) {
            return GameErrorCode.E_GOURD_CHILD_ACTIVITY_LOTUS_UPGRADE_ITEM_NO_ENOUGH;
        }
        userData.setLotusLv(1 + userData.getLotusLv());
        player.notifyListener(eGamePlayerEventType.GourdChildLotusLv.getValue(), userData.getLotusLv());
        return 0;
    }

    /**
     * 抽盲合
     */
    public int drawBox() {
        GourdChildConfig config = GourdChildMgr.getConfig();
        //前6次是否抽隐藏大奖
        boolean excludeHide = false;
        synchronized (userData) {
            if (userData.getTotalTimes() < config.getMountainLuckyParam().get(0)){
                excludeHide = true;
            }
            if (userData.getTotalTimes() < config.getMountainLuckyParam().get(0) && !userData.isGetSharedBox()) {
                boolean hide = new Random().nextInt(1000) < config.getMountainLuckyParam().get(2);
                if (hide) {
                    // 抽中，检查跨服是否有奖品
                    // 跨服再次判断
                    player.getModule(PreReduceModule.class).preReduce(config.getMountainConsume());
                    GourdChildProto.CrossGourdChildDrawHideBoxReqMsg.Builder builder = GourdChildProto.CrossGourdChildDrawHideBoxReqMsg.newBuilder();
                    builder.setActivityId(config.getActivityId());
                    builder.setServerId(GameServer.getInstance().getServerId());
                    player.sendPacket(CrossProtocol.C_GOURD_CHILD_ACTIVITY_DRAW_HIDE_BOX, builder);
                    return 0;
                }
            }
        }

        synchronized (userData) {
            GourdMountainItem item = getGourdMountainItem(config, excludeHide);

            return handleDrawResult(config, item);
        }
    }

    /**
     * 处理盲合奖励
     */
    public int handleDrawResult(GourdChildConfig config, GourdMountainItem item) {

        // 扣消耗
        if (!player.getModule(CurrencyModule.class).removeCurrency(PropertyHelper.parseStringToProperty(config.getMountainConsume()), eLogMoneyType.GourdChildActivity, eLogMoneyType.GourdChildDrawCost)) {
            return GameErrorCode.E_GOURD_CHILD_ACTIVITY_DRAW_ITEM_NO_ENOUGH;
        }

        if(item.isGrand()){
            //重置未抽中隐藏款次数
            userData.setCommonTimes(0);
        }else {
            //未抽中隐藏款次数+1
            userData.setCommonTimes(1 + userData.getCommonTimes());
        }

        // 加奖励
        String reward = item.getItemId() + "=1";
        player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.GourdChildActivity, eLogMoneyType.GourdChildDrawGet);

        userData.setTotalTimes(1 + userData.getTotalTimes());
        userData.getDrawBoxList().add(item.getItemId());


        // 上公告
        GourdChildProto.CrossGourdChildUploadNoticeReqMsg.Builder noticeBuilder = GourdChildProto.CrossGourdChildUploadNoticeReqMsg.newBuilder();
        //
        noticeBuilder.setActivityId(config.getActivityInfo().getActivityId());
        noticeBuilder.setPlayer(PlayerPb.parsePlayerBaseTempMsg(player.getUserInfo()));
        noticeBuilder.setGoodsId(item.getItemId());
        noticeBuilder.setType(item.isGrand() ? 1 : 2); // 1隐藏款，2普通
        player.sendPacket(CrossProtocol.C_GOURD_CHILD_ACTIVITY_UPLOAD_NOTICE, noticeBuilder);

        //抽奖日志
        LogGourdChildDraw drawLog = new LogGourdChildDraw(player.getUserId(), config.getActivityId(), item.getItemId());
        LogMgr.addLogGourdChildDraw(drawLog);

        GourdChildProto.GourdChildLotteryDrawRespMsg.Builder respMsg = GourdChildProto.GourdChildLotteryDrawRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setReward(reward);
        player.sendPacket(Protocol.U_GOURD_CHILD_LOTTERY_DRAW, respMsg);
        return 0;
    }

    /**
     * 获取隐藏款
     */
    public GourdMountainItem getGourdHideMountainItem(GourdChildConfig config) {
        List<GourdMountainItem> configList = config.getMountainItemList();
        List<Integer> weightList = new ArrayList<>();
        // 待抽取集合
        List<GourdMountainItem> itemList = new ArrayList<>();
        for (GourdMountainItem itemConfig : configList) {
            if(!itemConfig.isGrand()){
                continue;
            }
            weightList.add(itemConfig.getWeight());
            itemList.add(itemConfig);
        }
        // 抽
        Random random = new Random();
        int index = RandomHelper.getRandomIndexByWeight(weightList, random);
        return itemList.get(index);
    }

    /**
     * 正常抽
     */
    public GourdMountainItem getGourdMountainItem(GourdChildConfig config, boolean excludeHide) {
        // 正常抽取
        // 获取权重
        List<GourdMountainItem> configList = config.getMountainItemList();
        int additionWeight = 0;
        int addWeightMinTimes = config.getMountainAdditionParam().get(0);
        if(userData.getCommonTimes() > addWeightMinTimes){
            additionWeight += config.getMountainAdditionParam().get(1) * (userData.getCommonTimes() - addWeightMinTimes);
            log.debug("----------user {} 隐藏款加成 {}", player.getUserId(), additionWeight);
        }
        // 已上次抽中的奖品
        Set<Integer> itemSet = new HashSet<>();
        // 最后一次的奖品
        int lastItem = 0;
        if(userData.getDrawBoxList().size() > 0){
            lastItem = userData.getDrawBoxList().get(userData.getDrawBoxList().size() - 1);
        }
        for (int itemId : userData.getDrawBoxList()) {
            itemSet.add(itemId);
        }
        // 是否触发新奖励
        int totalCount = itemSet.size();
        int count = getDistinctCount(config);
        List<Integer> weightList = new ArrayList<>();
        // 待抽取集合
        List<GourdMountainItem> itemList = new ArrayList<>();
        for (GourdMountainItem itemConfig : configList) {
            // 保底，需扣除已获得
            if(count > totalCount){
                if(itemSet.contains(itemConfig.getItemId())){
                    continue;
                }
            }
            //是否与上次重复奖励
            if(lastItem == itemConfig.getItemId()){
                continue;
            }
            // 隐藏大奖
            if (excludeHide && itemConfig.isGrand()){
                continue;
            }
            if (itemConfig.isGrand()) {
                // 隐藏款加成
                weightList.add(itemConfig.getWeight() + additionWeight);
            } else {
                weightList.add(itemConfig.getWeight());
            }
            itemList.add(itemConfig);
        }

        // 抽
        Random random = new Random();
        int index = RandomHelper.getRandomIndexByWeight(weightList, random);
        return itemList.get(index);
    }

    /**
     * 获取保底需要满足几个不同的奖励
     */
    private int getDistinctCount(GourdChildConfig config){
        int count = 0;
        for (int i = 0; i < config.getControlList().size(); i++) {
            GourdMountainControl control = config.getControlList().get(i);
            if(userData.getTotalTimes() >= control.getTimes()){
                count = control.getDistinct();
            }
        }
        return count;
    }

    /**
     * 前6次必须共享跨服的大奖，不然就是普通奖励
     */
    public int drawBoxFromCross(boolean canHide) {
        GourdChildConfig config = GourdChildMgr.getConfig();
        if (config == null || ActivityMgr.activityInShowPeriod(config.getActivityInfo())) {
            return GameErrorCode.E_GOURD_CHILD_ACTIVITY_NO_OPEN;
        }
        if (userData == null) {
            return GameErrorCode.E_GOURD_CHILD_ACTIVITY_NO_UNLOCK;
        }

        // 返还预扣除
        player.getModule(PreReduceModule.class).restorePreReduce(config.getMountainConsume());

        synchronized (userData) {
            GourdMountainItem item;
            if (canHide) {
                item = getGourdHideMountainItem(config);
            } else {
                item = getGourdMountainItem(config, true);
            }
            int ret = handleDrawResult(config, item);
            if(ret == 0 && canHide){
                //中过大奖
                userData.setGetSharedBox(true);
            }
            return ret;
        }
    }

    /**
     * 扫荡关卡
     */
    public int mopUpPass(int passId, int times) {
        GourdChildConfig config = GourdChildMgr.getConfig();
        //关卡不存在
        if(!config.getLevelInfoMap().containsKey(passId)){
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }
        if(!userData.getPassStar().containsKey(passId)){
            return GameErrorCode.E_GOURD_CHILD_ACTIVITY_PASS_NO_WOP_UP;
        }
        if(userData.getPassStar().get(passId) < 3){
            return GameErrorCode.E_GOURD_CHILD_ACTIVITY_PASS_NO_WOP_UP;
        }

        GourdLevelInfo levelInfo = config.getLevelInfoMap().get(passId);
        int costEnergy = levelInfo.getEnergy() * times;
        // 体力
        if (userData.getEnergy() < costEnergy) {
            return GameErrorCode.E_GOURD_CHILD_ACTIVITY_ENERGY_NO_ENOUGH;
        }

        Property reward = PropertyHelper.parseStringToProperty(levelInfo.getReward());
        if(times > 1){
            reward.rideProperty(times);
        }
        //随机n次
        reward.addProperty(getRandomReward(levelInfo.getRandomReward(), times));

        //积分及冲榜
        addScoreAndRank(config, reward);

        player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.GourdChildActivity, eLogMoneyType.GourdChildWopUpGet);

        // 扣体力
        reduceEnergy(costEnergy, 2);
        syncUserData();

        //扫荡日志
        LogGourdChildMopUp mopUpLog = new LogGourdChildMopUp(player.getUserId(), config.getActivityId(), passId, PropertyHelper.parsePropertyToString(reward));
        LogMgr.addLogGourdChildMopUp(mopUpLog);

        GourdChildProto.GourdChildMopUpRespMsg.Builder respMsg = GourdChildProto.GourdChildMopUpRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setScore(userData.getScore());
        respMsg.setReward(PropertyHelper.parsePropertyToString(reward));
        player.sendPacket(Protocol.U_GOURD_CHILD_MOP_UP, respMsg);

        return 0;
    }

    /**
     * 积分及冲榜
     */
    public void addScoreAndRank(GourdChildConfig config, Property reward) {
        //拿出奖励的积分
        int score = reward.getCountByGoodsId(config.getScoreItemId()).intValue();
        if (score > 0) {
            userData.setScore(userData.getScore() + score);
        }
        //关卡冲榜
        if (userData.getPassId() > 0) {
            //ValueParamArgs args = new ValueParamArgs(userData.getPassId(), String.valueOf(userData.getScore()));
            //改为星级+积分；20210923上线前
            ValueParamArgs args = new ValueParamArgs(getTotalStar(), String.valueOf(userData.getScore()));
            player.notifyListener(eGamePlayerEventType.GourdChildPassProgressRank.getValue(), args);
            player.notifyListener(eGamePlayerEventType.GourdChildPassProgressCrossRank.getValue(), args);
        }
    }

    /**
     * 重排
     */
    public int resetPosition(int type) {
        if(type == 1) {
            if (userData.getPassDetail().getPassId() == 0) {
                return GameErrorCode.E_GOURD_CHILD_ACTIVITY_GRID_NO_INIT;
            }
        }else {
            if (userData.getTempPassDetail().getPassId() == 0) {
                return GameErrorCode.E_GOURD_CHILD_ACTIVITY_GRID_NO_INIT;
            }
        }
        List<Grid> gridList = userData.getGridList();
        if(type == 2){
            gridList = userData.getTempGridList();
        }
        int directionNum = eMoveDirectionType.values().length;
        for (eMoveDirectionType directionType : eMoveDirectionType.values()) {
            MoveMergerResult result = GourdChildMgr.move(gridList, directionType);
            if (result.getMovedIndexList().size() > 0) {
                directionNum--;
            }
        }
        if(directionNum != eMoveDirectionType.values().length){
            return GameErrorCode.E_GOURD_CHILD_GRID_NOT_NEED_RESET;
        }
        gridList = randomGridPosition(gridList);

        GourdChildConfig config = GourdChildMgr.getConfig();

        if(type == 1){
            userData.setGridList(gridList);
        }else {
            userData.setTempGridList(gridList);
        }

        GourdChildProto.GourdChildGridResetPositionRespMsg.Builder respMsg = GourdChildProto.GourdChildGridResetPositionRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setType(type);
        if(type ==1){
            GourdChildProto.GourdChildGameDataMsg.Builder gameData = GourdChildPb.parseGameDataMsg(userData, config);
            GourdChildMgr.appendMovableData(gameData, gridList, config);
            respMsg.setGameData(gameData);
        }else {
            GourdChildProto.GourdChildGameDataMsg.Builder gameData = GourdChildPb.parseTrainGameDataMsg(userData, config);
            GourdChildMgr.appendMovableData(gameData, gridList, config);
            respMsg.setGameData(gameData);
        }
        player.sendPacket(Protocol.U_GOURD_CHILD_GRID_RESET_POSITION, respMsg);

        return 0;
    }

    /**
     * 随机调换位置
     */
    private List<Grid> randomGridPosition(List<Grid> gridList) {
        List<Grid> tempGridList = GourdChildMgr.copyGridList(gridList);
        List<Grid> resultList = new ArrayList<>();
        Random random = new Random();
        while (tempGridList.size() > 0){
            int idx = random.nextInt(tempGridList.size());
            resultList.add(tempGridList.remove(idx));
        }
        return resultList;
    }

    /**
     * 快速挑战
     */
    public int fastPass(int passId) {
        if(userData == null){
            return GameErrorCode.E_GOURD_CHILD_ACTIVITY_NO_UNLOCK;
        }

        GourdChildConfig config = GourdChildMgr.getConfig();

        //关卡不存在
        if(!config.getLevelInfoMap().containsKey(passId)){
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }

        if(userData.getPassDetail().getPassId() > 0){
            return GameErrorCode.E_GOURD_CHILD_ACTIVITY_UN_CHALLENGE;
        }

        if(passId > userData.getHistoryPassId()){
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }

        GourdLevelInfo levelInfo = config.getLevelInfoMap().get(passId);

        // 体力
        if (userData.getEnergy() < levelInfo.getEnergy()) {
            return GameErrorCode.E_GOURD_CHILD_ACTIVITY_ENERGY_NO_ENOUGH;
        }

        //推荐伤害
        GourdLevelLotusInfo levelLotusInfo = config.getLotusInfoMap().get(userData.getLotusLv());
        if(levelLotusInfo.getDamage() < levelInfo.getAdviceDamage()){
            return GameErrorCode.E_GOURD_CHILD_FAST_PASS_DAMAGE_NO_MATCH;
        }

        // 扣体力
        reduceEnergy(levelInfo.getEnergy(), 5);

        //三星
        userData.getPassStar().put(passId, 3);
        if(passId > userData.getPassId()){
            userData.setPassId(passId);
        }
        Property rewardProperty = PropertyHelper.parseStringToProperty(levelInfo.getReward());
        rewardProperty.addProperty(getRandomReward(levelInfo.getRandomReward(), 1));
        //拿出奖励的积分
        addScoreAndRank(config, rewardProperty);
        player.getModule(CurrencyModule.class).addCurrency(rewardProperty, eLogMoneyType.GourdChildActivity, eLogMoneyType.GourdChildGridFastPassGet);

        player.notifyListener(eGamePlayerEventType.GourdChildPassTotalStar.getValue(), getTotalStar());

        //初始关卡
        userData.setGridList(GourdChildMgr.initGrid(GourdChildMgr.GRID_SIDE_LENGTH, config.getDefaultUnitNum(), levelInfo.getElement()));

        //关卡日志
        LogGourdChildPass passLog = new LogGourdChildPass(player.getUserId(), config.getActivityId(), passId, true, 3, 3, PropertyHelper.parsePropertyToString(rewardProperty));
        AutoLogMgr.add(passLog);

        GourdChildProto.GourdChildFastThroughRespMsg.Builder respMsg = GourdChildProto.GourdChildFastThroughRespMsg.newBuilder();
        respMsg.setRet(0);
        GourdChildProto.GourdChildGameDataMsg.Builder gameData = GourdChildPb.parseGameDataMsg(userData, config);

        GourdChildProto.GourdChildPassDataTemp.Builder pass = GourdChildProto.GourdChildPassDataTemp.newBuilder();
        pass.setPassId(0);
        pass.setBlood(0);
        pass.setRound(1);
        pass.setMonsterId(levelInfo.getMonster());
        pass.setHp(levelInfo.getHp());
        gameData.setPass(pass);
        respMsg.setGameData(gameData);
        respMsg.setReward(PropertyHelper.parsePropertyToString(rewardProperty));

        player.sendPacket(Protocol.U_GOURD_CHILD_FAST_THROUGH, respMsg);
        return 0;
    }
}
